using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.Diagnostics;
using EnvDTE80;

namespace wscf_lightblue_VSAddIn
{
	/// <summary>
	/// Represents Visual Studio IDE
	/// </summary>
	public class VisualStudio
	{
		#region Private Fields

		private DTE2 applicationObject;

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="VisualStudio"/> class.
		/// </summary>
		/// <param name="applicationObject">The application object.</param>
		public VisualStudio(DTE2 applicationObject)
		{
			this.applicationObject = applicationObject;
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Adds the task.
		/// </summary>
		/// <param name="description">The description.</param>
		/// <param name="category">The category.</param>
		/// <param name="subcategory">The subcategory.</param>
		/// <param name="priority">The priority.</param>
		/// <param name="icon">The icon.</param>
		/// <param name="checkable">if set to <c>true</c> [checkable].</param>
		/// <param name="releventFile">The relevent file.</param>
		/// <param name="lineNumber">The line number.</param>
		/// <param name="canUserDelete">if set to <c>true</c> [can user delete].</param>
		/// <param name="flushItem">if set to <c>true</c> [flush item].</param>
		/// <param name="allowDuplicates">if set to <c>true</c> [allow duplicates].</param>
		public void AddTask(string description,
				string category,
				string subcategory,
				vsTaskPriority priority,
				vsTaskIcon icon,
				bool checkable,
				string releventFile,
				int lineNumber,
				bool canUserDelete,
				bool flushItem,
				bool allowDuplicates)
		{
			Debug.Assert(description != null, "description parameter could not be null.");
			Debug.Assert(category != null, "category parameter could not be null.");
			Debug.Assert(subcategory != null, "subcategory parameter could not be null.");

			// Get a reference to the tasks window.
			Window win = applicationObject.Windows.Item(EnvDTE_Constants.vsWindowKindTaskList);
			// Activate it.
			win.Activate();
			// Get a reference to the tasks list.
			TaskList taskList = (TaskList)win.Object;

			// If we don't allow duplicates we have to itterate the tasks list to 
			// see if there is a duplicate.

			// Do this for all task items.
			for (int ti = 1; ti <= taskList.TaskItems.Count; ti++)
			{
				// Get a reference to the task item.
				TaskItem existingItem = taskList.TaskItems.Item(ti);
				// Match attributes and see if this task is as same as the one being added.
				// If the task is matching all Category, SubCategory and Description properties
				// must be similar to the pertaining parameters. We don't care about the case here.
				if (string.Compare(category, existingItem.Category, true) == 0 &&
						string.Compare(subcategory, existingItem.SubCategory, true) == 0 &&
						string.Compare(description, existingItem.Description, true) == 0)
				{
					// We don't have to proceed.
					return;
				}
			}

			// Add the new task item.
			TaskItem newItem = taskList.TaskItems.Add(category, subcategory, description, priority, icon,
					checkable, releventFile, lineNumber, canUserDelete, flushItem);

			// Finally activate the task bar.
			ActivateTaskBar();
		}

		public void OpenFile(string fileName)
		{
			ItemOperations ItemOp = applicationObject.ItemOperations;
			ItemOp.OpenFile(fileName, Constants.vsViewKindPrimary);
		}

		#endregion

		#region Public Properties

		/// <summary>
		/// Gets the currently selected project.
		/// </summary>
		public VisualStudioProject SelectedProject
		{
			get
			{
				// First try to read the project from the selected item (assuming a project is 
				// currently selected). 
				Project selectedProject = this.applicationObject.SelectedItems.Item(1).Project;

				// Do we have a project?
				if (selectedProject != null)
				{
					return new VisualStudioProject(selectedProject);
				}

				// If not, try to read the project containing the currently selected item.
				ProjectItem projectItem = applicationObject.SelectedItems.Item(1).ProjectItem;
				if (projectItem != null)
				{
					selectedProject = projectItem.ContainingProject;
					return new VisualStudioProject(selectedProject);
				}

				// No, we could not find the project. So returning null.
				return null;
			}
		}

		/// <summary>
		/// Gets a value indicating whether this instance is item selected.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is item selected; otherwise, <c>false</c>.
		/// </value>
		public bool IsItemSelected
		{
			get
			{
				return (this.applicationObject.SelectedItems.Count > 0 &&
						this.applicationObject.SelectedItems.SelectionContainer != null &&
						this.applicationObject.SelectedItems.SelectionContainer.Count > 0);
			}
		}

		/// <summary>
		/// Gets the selected item.
		/// </summary>
		public VisualStudioSelectedItem SelectedItem
		{
			get
			{
				if (this.applicationObject.SelectedItems.Count == 0)
				{
					return null;
				}
				return new VisualStudioSelectedItem(this.applicationObject.SelectedItems.Item(1));
			}
		}

		/// <summary>
		/// Gets the selected items.
		/// </summary>
		public IEnumerable<VisualStudioSelectedItem> SelectedItems
		{
			get
			{
				foreach (SelectedItem item in applicationObject.SelectedItems)
				{
					yield return new VisualStudioSelectedItem(item);
				}
			}
		}

		/// <summary>
		/// Gets the application object.
		/// </summary>
		public DTE2 ApplicationObject
		{
			get { return applicationObject; }
		}

		#endregion

		#region Private Methods

		/// <summary>
		/// Helper method to activate the task bar.
		/// Usually invoked when a new item is added to the task bar.
		/// </summary>
		private void ActivateTaskBar()
		{
			object cin = "Add-ins and Macros";
			object cout = new object();

			this.applicationObject.Commands.Raise("{1496A755-94DE-11D0-8C3F-00C04FC2AAE2}", 2200,
							ref cin, ref cout);
		}

		#endregion
	}
}
